package Controller

import (
	"back_go/Common"
	"back_go/Common/MenuType"
	"back_go/DAO"
	"back_go/DAO/gorm"
	"back_go/DAO/gorm/GormModel"
	models "back_go/DAO/model"
	"back_go/Response"
	"back_go/Util"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-xorm/xorm"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"
)

type SysMenu struct {
	MenuID   int64     `json:"menuId"`
	ParentID int64     `json:"parentId"`
	Name     string    `json:"name"`
	URL      string    `json:"url"`
	Perms    string    `json:"perms"`
	Type     int       `json:"type"`
	Icon     string    `json:"icon"`
	OrderNum int       `json:"order_num"`
	List     []SysMenu `json:"list,omitempty"`
}

type MenuResponse struct {
	MenuList    interface{} `json:"menuList"`
	Authorities interface{} `json:"authorities"`
}

const SUPER_ADMIN_ID = 1
const SYS_MENU_MAX_ID = 1

// GetMenuNav 获取菜单列表
// @Summary 获取菜单列表 将 models.TzSysMenu 转换为 SysMenu 类型
/*
   参数：
	@param menu models.TzSysMenu
   	return: 菜单列表
*/
func convertToSysMenu(menu models.TzSysMenu) SysMenu {
	return SysMenu{
		MenuID:   menu.MenuId,
		ParentID: menu.ParentId,
		Name:     menu.Name,
		URL:      menu.Url,
		Perms:    menu.Perms,
		Type:     menu.Type,
		Icon:     menu.Icon,
		OrderNum: menu.OrderNum,
	}
}

// processMenus 处理菜单数据
/*
   参数：
	@param menus []models.TzSysMenu
   	return: 菜单列表
*/
func processMenus(menus []models.TzSysMenu) []SysMenu {
	// 按照 OrderNum 排序
	sort.Slice(menus, func(i, j int) bool {
		return menus[i].OrderNum < menus[j].OrderNum
	})

	sysMenuLevelMap := make(map[int64][]models.TzSysMenu)
	for _, menu := range menus {
		sysMenuLevelMap[menu.ParentId] = append(sysMenuLevelMap[menu.ParentId], menu)
	}

	// 一级菜单
	rootMenus := sysMenuLevelMap[0]
	if len(rootMenus) == 0 {
		return []SysMenu{}
	}

	var result []SysMenu
	for _, rootMenu := range rootMenus {
		newRoot := convertToSysMenu(rootMenu)
		newRoot.List = getChildren(sysMenuLevelMap, rootMenu.MenuId)
		result = append(result, newRoot)
	}

	return result
}

// queryAllPerms 查询所有权限
/*
  参数：
	@param userId int64
	@param engine *xorm.Engine
  return: 权限列表
*/
func queryAllPerms(userId int64, engine *xorm.Engine) ([]string, error) {
	var perms []string
	err := engine.Table("tz_sys_user_role").
		Join("LEFT", "tz_sys_role_menu", "tz_sys_user_role.role_id = tz_sys_role_menu.role_id").
		Join("LEFT", "tz_sys_menu", "tz_sys_role_menu.menu_id = tz_sys_menu.menu_id").
		Where("tz_sys_user_role.user_id =?", userId).
		Select("tz_sys_menu.perms").
		Find(&perms)
	return perms, err
}

// getChildren 获取子菜单
/*
  参数：
	@param sysMenuLevelMap map[int64][]models.TzSysMenu
	@param parentId int64
  return: 子菜单列表
*/
func getChildren(sysMenuLevelMap map[int64][]models.TzSysMenu, parentId int64) []SysMenu {
	children := sysMenuLevelMap[parentId]
	var result []SysMenu
	for _, child := range children {
		if child.Type != 2 {
			newChild := convertToSysMenu(child)
			newChild.List = getChildren(sysMenuLevelMap, child.MenuId)
			result = append(result, newChild)
		}
	}
	return result
}

func verifyForm(menu GormModel.TzSysMenu) (bool, error) {
	if menu.Type == MenuType.MENU.GetValue() {
		if Util.IsBlank(menu.Url) {
			return false, fmt.Errorf("菜单URL不能为空")
		}
	}
	if menu.MenuId == menu.ParentId {
		return false, fmt.Errorf("自己不能是自己的上级")
	}

	//上级菜单类型
	parentType := MenuType.CATALOG.GetValue()
	if parentType != 0 {
		db := gorm.Db
		var parentMenu models.TzSysMenu
		db.Table("tz_sys_menu").Where("menu_id = ?", menu.ParentId).First(&parentMenu)
		parentType = parentMenu.Type
	}

	//目录、菜单
	if menu.Type == MenuType.CATALOG.GetValue() ||
		menu.Type == MenuType.MENU.GetValue() {
		if parentType != MenuType.CATALOG.GetValue() {
			return false, fmt.Errorf("上级菜单只能为目录类型")
		}
		return true, nil
	}

	//按钮
	if menu.Type == MenuType.BUTTON.GetValue() {
		if parentType != MenuType.MENU.GetValue() {
			return false, fmt.Errorf("上级菜单只能为菜单类型")
		}
	}
	return true, nil
}

// GetMenuNav 获取菜单列表
// @Summary 获取菜单列表
/*
   参数：
	@param c *gin.Context
  return: 菜单列表
*/
func GetMenuNav(c *gin.Context) {
	var engine = DAO.Engine
	var Userid, _, _ = Common.CodeToken(c.GetHeader("Authorization"))
	//fmt.Println("获取菜单用户ID", Userid)

	//系统管理员，拥有最高权限
	if Userid == SUPER_ADMIN_ID {

		//查询所有菜单
		var menus []models.TzSysMenu
		err := engine.Find(&menus)

		MenuResult := processMenus(menus)

		var MenuResponse = MenuResponse{
			MenuList: MenuResult,
		}
		permsList := make([]string, 0)
		for _, menu := range menus {
			if menu.Perms != "" {
				permsList = append(permsList, menu.Perms)
			}
		}

		uniquePerms := make(map[string]struct{})
		for _, perms := range permsList {
			parts := strings.Split(perms, ",")
			for _, part := range parts {
				trimmedPart := strings.TrimSpace(part)
				if trimmedPart != "" {
					uniquePerms[trimmedPart] = struct{}{}
				}
			}
		}

		result := make([]string, 0, len(uniquePerms))
		for key := range uniquePerms {
			result = append(result, key)
		}
		MenuResponse.Authorities = result
		if err != nil {
			c.JSON(http.StatusOK, Response.ResponseBody{
				Code:      "00000",
				Msg:       "没有数据",
				Data:      nil,
				Version:   "1.0",
				Timestamp: time.Now().Unix(),
				Sign:      "",
				Success:   true,
				Fail:      false,
			})
			return
		}
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "00000",
			Msg:       "成功",
			Data:      MenuResponse,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
			Fail:      false,
		})
	} else {
		//查询所有菜单
		var menus []models.TzSysMenu
		_ = engine.Find(&menus)

		MenuResult := processMenus(menus)

		var MenuResponse = MenuResponse{
			MenuList: MenuResult,
		}
		permsList := make([]string, 0)
		for _, menu := range menus {
			if menu.Perms != "" {
				permsList = append(permsList, menu.Perms)
			}
		}

		uniquePerms := make(map[string]struct{})
		for _, perms := range permsList {
			parts := strings.Split(perms, ",")
			for _, part := range parts {
				trimmedPart := strings.TrimSpace(part)
				if trimmedPart != "" {
					uniquePerms[trimmedPart] = struct{}{}
				}
			}
		}
		query := "SELECT m.perms FROM tz_sys_user_role ur LEFT JOIN tz_sys_role_menu rm ON ur.role_id = rm.role_id LEFT JOIN tz_sys_menu m ON rm.menu_id = m.menu_id WHERE ur.user_id =?"

		results, _ := engine.Query(query, Userid)

		var perms []string
		for _, row := range results {
			if perm, ok := row["perms"]; ok {
				if perm != nil {
					strPerm := string(perm)
					if strPerm != "" {
						parts := strings.Split(strPerm, ",")
						for _, part := range parts {
							trimmedPart := strings.TrimSpace(part)
							if trimmedPart != "" {
								perms = append(perms, trimmedPart)
							}
						}
					}
				}
			}
		}
		MenuResponse.Authorities = perms
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "00000",
			Msg:       "成功",
			Data:      MenuResponse,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
			Fail:      false,
		})
	}
}

func GetMenuTable(c *gin.Context) {
	db := gorm.Db

	var menu []GormModel.TzSysMenu
	err := db.Table("tz_sys_menu").Find(&menu).Order("order_num").Error
	if err != nil {
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "00000",
			Msg:       "没有数据",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Msg:       "成功",
		Data:      menu,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}

/*
GetMenuList
获取用户所拥有的菜单(不包括按钮) 用于新建、修改角色时 获取菜单的信息
*/
func GetMenuList(c *gin.Context) {
	db := gorm.Db

	var menuList []GormModel.TzSysMenu
	//select menu_id ,parent_id ,`name` from tz_sys_menu where `type` != 2 order by order_num

	err := db.Table("tz_sys_menu").Where("type!= 2").Order("order_num").Find(&menuList).Error
	if err != nil {
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "00000",
			Msg:       "没有数据",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Msg:       "成功",
		Data:      menuList,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}

/*
GetMenuListRoot
选择菜单
*/
func GetMenuListRoot(c *gin.Context) {
	db := gorm.Db
	var menuList []GormModel.TzSysMenu
	//select menu_id,`name` from tz_sys_menu where `type` = 0
	err := db.Table("tz_sys_menu").Where("type= 0").Order("order_num").Find(&menuList).Error
	if err != nil {
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "00000",
			Msg:       "没有数据",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Msg:       "成功",
		Data:      menuList,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}

func GetListChildrenMenu(c *gin.Context) {
	parentId, _ := strconv.Atoi(c.Query("parentId"))
	db := gorm.Db
	var menuList []GormModel.TzSysMenu
	//select menu_id,`name` from tz_sys_menu where parent_id = #{parentId}
	err := db.Table("tz_sys_menu").Where("parent_id= ?", parentId).Order("order_num").Find(&menuList).Error
	if err != nil {
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "00000",
			Msg:       "没有数据",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Msg:       "成功",
		Data:      menuList,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}

/*
GetListInfoByMenuId
菜单信息
*/
func GetListInfoByMenuId(c *gin.Context) {
	menuIdStr := c.Param("menuId")
	menuId, _ := strconv.Atoi(menuIdStr)
	db := gorm.Db
	var menu GormModel.TzSysMenu
	//select * from tz_sys_menu where menu_id = #{menuId}
	err := db.Model(GormModel.TzSysMenu{}).Where("menu_id=?", menuId).Find(&menu).Error
	if err != nil {
		c.JSON(http.StatusOK, Response.ResponseBody{
			Code:      "00000",
			Msg:       "没有数据",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Msg:       "成功",
		Data:      menu,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}

func SaveMenu(c *gin.Context) {
	var menu GormModel.TzSysMenu
	if err := c.ShouldBindJSON(&menu); err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00001",
			Msg:       "参数错误",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	isPass, err := verifyForm(menu)
	if !isPass {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00001",
			Msg:       err.Error(),
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	db := gorm.Db
	//
	if db.Save(&menu).Error != nil {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00001",
			Msg:       "保存失败",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
	}

}

func UpdateMenu(c *gin.Context) {
	var menu GormModel.TzSysMenu
	if err := c.ShouldBindJSON(&menu); err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00001",
			Msg:       "参数错误",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	isPass, err := verifyForm(menu)
	if !isPass {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00001",
			Msg:       err.Error(),
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	if menu.Type == MenuType.MENU.GetValue() {
		if Util.IsBlank(menu.Url) {
			c.JSON(200, Response.ResponseBody{
				Code:      "A00001",
				Msg:       "菜单URL不能为空",
				Data:      nil,
				Version:   "1.0",
				Timestamp: time.Now().Unix(),
				Sign:      "",
				Success:   true,
			})
			return
		}
	}
	db := gorm.Db
	db.Save(menu)
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Msg:       "成功",
		Data:      nil,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}

func DelMenuByMenuId(c *gin.Context) {
	menuIdStr := c.Param("menuId")
	menuId, _ := strconv.Atoi(menuIdStr)

	if menuId <= SYS_MENU_MAX_ID {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00001",
			Msg:       "系统菜单不能删除",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	db := gorm.Db
	//	select menu_id,`name` from tz_sys_menu where parent_id = #{parentId}
	var menuList []GormModel.TzSysMenu
	db.Table("tz_sys_menu").Where("parent_id=?", menuId).Find(&menuList)
	if Util.SliceIsNotEmpty(menuList) {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00001",
			Msg:       "请先删除子菜单",
			Data:      nil,
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}

	db.Delete(&GormModel.TzSysMenu{}, menuId)
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Msg:       "成功",
		Data:      nil,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}
